package lib.relay;

public class ThreadCtrlBase implements Runnable {
	public interface ThreadRunListener {
		void ThreadRun(int iID);
	}

	private ThreadRunListener m_RunListener = null;

	private static final int iMaxStopThreadWaitTime = 3000;

	private int iThreadID = 0;
	private static final byte TYPE_READ = 0x01;
	private static final byte TYPE_WRITE = 0x02;

	private static final int STATUS_TERMINAL = 0x01;
	private static final int STATUS_RUNNING = 0x02;
	private static final int STATUS_STOPPING = 0x03;

	private int iSendStatus = STATUS_TERMINAL;
	private Thread m_Thread = null;
	boolean bIsRunOnce = false;

	public ThreadCtrlBase(int iID, ThreadRunListener l, boolean bIsRunOnceIn) {
		iThreadID = iID;
		m_RunListener = l;
		bIsRunOnce = bIsRunOnceIn;
	}

	public void startThread() {
		// ***Log.e("@@@@@@@@@@ Remote Control Log @@@@@@@@@@","start Thread:0");

		if (CtrlStatusFlag(TYPE_READ, 0) == STATUS_RUNNING)
			return;
		// ***Log.e("@@@@@@@@@@ Remote Control Log @@@@@@@@@@","start Thread:1");

		CtrlStatusFlag(TYPE_WRITE, STATUS_RUNNING);
		m_Thread = new Thread(this);
		m_Thread.start();
	}

	public boolean IsThreadRun() {
		if (CtrlStatusFlag(TYPE_READ, 0) == STATUS_RUNNING)
			return true;
		else
			return false;
	}

	public void stopThread() {
		// ***Log.e("@@@@@@@@@@ Remote Control Log @@@@@@@@@@","stop Thread:1");

		if (m_Thread != null) {
			if (CtrlStatusFlag(TYPE_READ, 0) == STATUS_RUNNING) {
				CtrlStatusFlag(TYPE_WRITE, STATUS_STOPPING);

				m_Thread.interrupt();
				int iSleepInterval = 100;
				int iTotalSleepTime = 0;
				while (CtrlStatusFlag(TYPE_READ, 0) != STATUS_TERMINAL) {
					this.sleep(iSleepInterval);
					iTotalSleepTime += iSleepInterval;
					if (iTotalSleepTime >= iMaxStopThreadWaitTime)
						break;
				}

				m_Thread = null;
			}
		}
	}

	private synchronized int CtrlStatusFlag(byte btType, int iValue) {
		int iReturn = 0;

		if (btType == TYPE_READ)
			iReturn = iSendStatus;
		else if (btType == TYPE_WRITE)
			iSendStatus = iValue;

		return iReturn;
	}

	public void run() {
		if (bIsRunOnce == false) {
			while (CtrlStatusFlag(TYPE_READ, 0) == STATUS_RUNNING) {
				if (m_RunListener != null) {
					m_RunListener.ThreadRun(iThreadID);
				}
			}
		} else {
			if (m_RunListener != null) {
				m_RunListener.ThreadRun(iThreadID);
			}
		}
		CtrlStatusFlag(TYPE_WRITE, STATUS_TERMINAL);
		// ***Log.e("@@@@@@@@@@ Remote Control Log @@@@@@@@@@","Out Thread:"+iThreadID);
	}

	public void sleep(int time) {
		try {
			Thread.sleep(time);
		} catch (Exception ee) {
		}
	}

	public final byte TYPE_WAIT = 0x01;
	public final byte TYPE_NOTIFY = 0x02;

	public void WaitAndNotify(int iType, int iMaxWaitTime) {
		try {

			if (iType == TYPE_WAIT) {
				synchronized (m_Thread) {
					if (iMaxWaitTime == -1)
						m_Thread.wait();
					else
						m_Thread.wait(iMaxWaitTime);
				}
			} else {
				synchronized (m_Thread) {
					m_Thread.notify();
				}
			}
		} catch (Exception ee) {
		}
	}
}
